# -*- coding: utf-8 -*-
# @Organization  : asiainfo
# @Author        : 周伟东
# @Time          : 2021/1/8 11:27
# @Function      : 调用资产探测so代码
import ctypes
import json
import logging
from ctypes import *
from config import APP_DIR


class AssetSoCaller:
    def __init__(self):
        self.asset_caller = cdll.LoadLibrary(APP_DIR + '/app/libs/coreprobe.so')

    def get_alive_info(self, ip):
        """
       desc: 探测主机的操作系统信息
       {"state":"up","ip":"192.168.1.184","hostName":"asap184","timeConsuming":"3.04","endTime":"2021-01-15 11:18:36"}
       param: ip IP地址
       return: 主机操作系统信息（json字符串）
       """
        logging.debug("进入get_alive_info方法")
        self.asset_caller.aliveProbe.restype = ctypes.c_char_p
        info = self.asset_caller.aliveProbe(ip.encode("utf-8"))
        alive_info = ctypes.string_at(info, -1)
        # 判空
        if not alive_info:
            return [False, ip, "{}", "{}"]
        logging.debug("alive_info: %s" % alive_info)
        alive_json = json.loads(alive_info)
        if alive_json['state'] and alive_json['state'] == 'up':
            os_json = json.loads(self.get_os_info(ip))
            for key in alive_json.keys():
                os_json[key] = alive_json[key]
            return [True, ip, json.dumps(os_json)]
        else:
            return [False, ip, alive_info]

        # return [True, ip,
        #        '{"state":"up", "ip":"192.168.1.184", "hostName":"asap184","deviceType":"general purpose","os":"Linux 3.X|4.X","osVersion":"Linux 3.8 - 4.14","networkDistance":"0 hops","timeConsuming":"2.65","endTime":"2021-01-15 11:21:20" }']

    def get_os_info(self, ip):
        """
        desc: 探测主机的操作系统信息
        {"deviceType":"general purpose","os":"Linux 3.X|4.X","osVersion":"Linux 3.8 - 4.14","networkDistance":"0 hops","timeConsuming":"2.65","endTime":"2021-01-15 11:21:20"}
        param: ip IP地址
        return: 主机操作系统信息（json字符串）
        """
        logging.debug("进入get_os_info方法")
        self.asset_caller.osProbe.restype = ctypes.c_char_p
        info = self.asset_caller.osProbe(ip.encode("utf-8"))
        os_info = ctypes.string_at(info, -1)
        # 判空
        if not os_info:
            return "{}"
        logging.debug("os_info: %s" % os_info)
        return os_info
        # return '{"deviceType":"general purpose","os":"Linux 3.X|4.X","osVersion":"Linux 3.8 - 4.14","networkDistance":"0 hops","timeConsuming":"2.65","endTime":"2021-01-15 11:21:20"}'

    def get_server_info(self, ip, port):
        """
        desc: 探测主机的服务
        '{"port:"22/tcp","state:"open","service:"ssh","version:"OpenSSH 7.4 (protocol 2.0)","timeConsuming":"2.87","endTime":"2021-01-15 03:10:18"}'
        param: ip IP地址
        param: port 端口
        return: [True, ip, port, 服务的信息（json字符串）]
        """
        logging.debug("进入get_server_info方法")
        self.asset_caller.serviceProbe.restype = ctypes.c_char_p
        info = self.asset_caller.serviceProbe(ip.encode("utf-8"), port)
        server_info = ctypes.string_at(info, -1)
        # 判空
        if not server_info:
            return [False, ip, port, {}]
        # server_info = '{"port":"22","protocol":"tcp","state":"open","service":"ssh","version":"OpenSSH 7.4 (protocol 2.0)","timeConsuming":"2.87","endTime":"2021-01-15 03:10:18"}'
        logging.debug("server_info: %s" % server_info)
        server_json = json.loads(server_info)
        if server_json['state'] and server_json['state'] == 'open':
            return [True, ip, port, server_info]
        else:
            return [False, ip, port, server_info]

    def get_assets_info(self, ip, port_scope):
        """
        desc: 探测主机的所有资产
        param: ip IP地址
        param: port_scope 端口范围
        return: [True, ip, port_scope, 服务的信息（json字符串）]
        {"state":"up","ip":"192.168.1.184","hostName":"asap184","deviceType":"general purpose","os":"Linux 3.X|4.X","osVersion":"Linux 3.8 - 4.14","networkDistance":"0 hops",
        "services":[
        {"port:"13/tcp","state:"closed","service:"daytime"},
        {"port:"14/tcp","state:"closed","service:"unknown"},
        {"port:"15/tcp","state:"closed","service:"netstat"},
        {"port:"16/tcp","state:"closed","service:"unknown"},
        {"port:"17/tcp","state:"closed","service:"qotd"},
        {"port:"18/tcp","state:"closed","service:"msp"},
        {"port:"19/tcp","state:"closed","service:"chargen"},
        {"port:"20/tcp","state:"closed","service:"ftp-data"},
        {"port:"21/tcp","state:"closed","service:"ftp"},
        {"port:"22/tcp","state:"open","service:"ssh","version:"OpenSSH 7.4 (protocol 2.0)"}
        ],"timeConsuming":"2.82","endTime":"2021-01-19 04:01:39"}
        """
        logging.debug("进入get_assets_info方法")
        self.asset_caller.assetsProbe.restype = ctypes.c_char_p
        assets_info = self.asset_caller.assetsProbe(ip.encode('utf-8'), port_scope.encode('utf-8'))
        self.asset_caller.freeMemory()
        if not assets_info:
            return [False, ip, {}]
        logging.debug("asserts_info: %s" % assets_info)
        assets_json = json.loads(assets_info)
        if assets_json['state'] and assets_json['state'] == 'up':
            return [True, ip, assets_info]
        return [False, ip, assets_info]
        # return [False, ip,
        #         '{"state":"up","ip":"192.168.1.184","hostName":"asap184","mac":"HH:AA:BB:CC:DD","macVendor":"abcdefg","deviceType":"general purpose","os":"Linux 3.X|4.X","osVersion":"Linux 3.8 - 4.14","networkDistance":"0 hops","services":[{"port":"13 / tcp ","state":"closed","service":"daytime" },{"port":"14 / tcp ","state":"closed","service":"unknown "},{"port":"22 / tcp ","state":"open","protocol":"xieyi","service":"ssh ","version":"OpenSSH 7.4 (protocol 2.0)"}],"timeConsuming":"2.82","endTime":"2021-01-19 04:01:39"}'
        #         ]

    def initProbe(self, ports):
        """
        desc: 初始化 ports
        """
        self.asset_caller.initProbe(ports.encode("utf-8"))

    def get_assets_info_by_ip(self, ip):
        """
        desc： 通过ip 探索服务，与initProbe 以及 freeProbe配合使用
        """
        logging.debug("进入get_assets_info_by_ip方法")
        self.asset_caller.assetsProbe.restype = ctypes.c_char_p
        assets_info = self.asset_caller.assetsProbe(ip.encode("utf-8"))
        if not assets_info:
            return [False, ip, {}]
        logging.debug("asserts_info: %s" % assets_info)
        assets_json = json.loads(assets_info)
        if assets_json['state'] and assets_json['state'] == 'up':
            return [True, ip, assets_info]
        return [False, ip, assets_info]

    def freeProbe(self):
        # 释放本次任务占用内存
        self.asset_caller.freeProbe()


assetSoCaller = AssetSoCaller()
